package amtf

import (
	"encoding/json"
	"fmt"
	"reflect"
	"server/global"
	"strings"

	"gorm.io/gorm"
)

type Sservice struct {
	A组件 *S组件 `json:"-"`
}

func (a *Sservice) A增(model any) (err error) {
	if a.A组件.A手动挡.A增s7 != nil {
		if A反射调用(a.A组件.A手动挡.A增s7, model) != nil {
			return err
		}
		return
	}
	err = global.GVA_DB.Create(model).Error
	return err
}

func (a *Sservice) A删(ids any, models any) (err error) {
	err = global.GVA_DB.Delete(models, "id in ?", ids).Error
	return err
}

func (a *Sservice) A删ff(ids any, model any) (err error) {
	_, models, _ := A解构组件(a.A组件)

	switch ids.(type) {
	case string:
		err = global.GVA_DB.Delete(model, "id = ?", ids).Error
		return err
	case []string:
		// model切片 := A成切片(model)
		err = global.GVA_DB.Delete(models, "id in ?", ids).Error
		// 非反射的形式👇
		// err = global.GVA_DB.Delete(&[]Smodel{}, "id in ?", ids).Error
		return err
	default:
		return gorm.ErrInvalidData
	}
}

// func (a *Sservice) A删除ByIds(IDs []string) (err error) {
// 	err = global.GVA_DB.Delete(&[]Smodel{}, "id in ?", IDs).Error
// 	return err
// }

func (a *Sservice) A改(model any) (err error) {
	id := A取id(model)
	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if a.A组件.A手动挡.A改之前s7 != nil {
			// 获取 A改之前s7 函数的反射值
			// fnValue := reflect.ValueOf(a.A组件.A手动挡.A改之前s7)
			// // 检查函数是否可调用
			// if fnValue.Kind() == reflect.Func {
			// 	// 创建输入参数切片
			// 	input := []reflect.Value{reflect.ValueOf(model)}
			// 	// 调用函数
			// 	results := fnValue.Call(input)
			// 	// 获取返回的错误值
			// 	if len(results) > 0 && !results[0].IsNil() {
			// 		err, _ = results[0].Interface().(error)
			// 		return err
			// 	}
			// }
			if A反射调用(a.A组件.A手动挡.A改之前s7, model) != nil {
				return err
			}
		}
		// 处理主表
		if err = tx.Model(&model).Where("id =?", id).Updates(model).Error; err != nil {
			return err
		}

		// 处理关联记录
		for _, 字段 := range a.A组件.A字段组 {
			switch 字段.A类型 {
			case "关联记录":
				关联id := 字段.A关联属性["关联id"]
				关联类型 := 字段.A关联属性["关联类型"]
				关联组件 := A组件集[关联id]

				if 关联类型 == "一对多" {
					子表model := 关联组件.Amodel
					关联字段名 := 字段.Name_go
					子表单项组 := A取字段反射值(model, 关联字段名)
					外键字段名 := 字段.A外键字段名
					// 增和改👇
					for i := 0; i < 子表单项组.Len(); i++ {
						子表单项 := A取反射值元素(子表单项组.Index(i))
						子表单项any := A取反射值接口(子表单项)

						子表单项id := A取id(子表单项)
						if 子表单项id == 0 {
							// 新增
							// 通过外键字段名用反射找到外键字段
							外键字段 := 子表单项.FieldByName(外键字段名)
							外键字段.SetUint(uint64(id))
							if err = tx.Create(子表单项any).Error; err != nil {
								return err
							}
						} else {
							// 更新
							if err = tx.Model(子表model).Where("id =?", 子表单项id).Updates(子表单项any).Error; err != nil {
								return err
							}
						}
					}

					// 批量删除ids👇
					ids := A取字段值_数组(model, "A拟删除子表ids")
					if ids == nil {
						return nil
					}
					子表单项切片 := A成切片(子表model)
					// Unscoped 绕过软删除使用物理删除👇
					err = tx.Unscoped().Delete(子表单项切片, "id in ?", ids).Error
					if err != nil {
						return err
					}
				}
			}
		}
		return nil
	})
	return err
}

func (a *Sservice) A改多个(models any) (err error) {
	models反射值 := reflect.ValueOf(models)
	if models反射值.Kind() == reflect.Ptr {
		models反射值 = models反射值.Elem()
	}
	// 检查 models 是否为切片类型
	if models反射值.Kind() != reflect.Slice {
		return fmt.Errorf("models is not a slice")
	}
	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		for i := 0; i < models反射值.Len(); i++ {
			model := models反射值.Index(i).Interface()
			// 获取 model 的 reflect.Value
			model反射值 := reflect.ValueOf(model)
			// 如果 model 是指针，获取其指向的值
			if model反射值.Kind() == reflect.Ptr {
				model反射值 = model反射值.Elem()
			}
			// 获取 ID 字段的值
			idField := model反射值.FieldByName("ID")
			id := idField.Interface()

			if err = tx.Model(model).Where("id =?", id).Updates(model).Error; err != nil {
				return err
			}
		}
		return nil
	})
	return err
}

func (a *Sservice) A查单个(ID string) (model any, err error) {
	model, _, _ = A解构组件(a.A组件)
	// model = A实例转指针(model)
	// err = global.GVA_DB.Where("id = ?", ID).First(model).Error

	// 创建一个 gorm.DB 实例用于链式调用
	db := global.GVA_DB.Debug().Where("id = ?", ID)

	关联查询(db, a.A组件)

	err = db.First(model).Error
	return
}

func (a *Sservice) A成字段值选项集() (res map[string][]map[string]any, err error) {
	res = make(map[string][]map[string]any)
	for _, 字段 := range a.A组件.A字段组 {
		var 字段值选项 map[string]any
		err = json.Unmarshal([]byte(字段.A字段值选项), &字段值选项)
		if 字段值选项 == nil {
			continue
		}
		类型 := 字段值选项["类型"]
		单项组 := make([]map[string]any, 0)
		表名 := fmt.Sprintf("%s_%s", a.A组件.A插件名, a.A组件.Name)
		if 类型 != "自关联" {
			表名 = strings.Replace(字段值选项["关联"].(string), ".", "_", -1)
		}
		lable := 字段值选项["lable"]
		value := 字段值选项["value"]

		global.GVA_DB.Table(表名).Where("deleted_at IS NULL").Select(fmt.Sprintf("%s as label, %s as value", lable, value)).Scan(&单项组)
		// global.GVA_DB.Table("lysd_商品").Where("deleted_at IS NULL").Select("类别 as label,id as value").Scan(&父级id)
		res[字段.Name] = 单项组

	}
	return
}

func (a *Sservice) A查(info S列表req) (models any, total int64, err error) {
	model, models, _ := A解构组件(a.A组件)

	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// model := 组件.Amodel
	// models = 组件.Amodels

	db := global.GVA_DB.Model(model)

	// 处理关联记录
	// for _, 字段 := range a.A组件.A字段组 {
	// 	switch 字段.A类型 {
	// 	case "关联记录":
	// 		关联属性 := 字段.A关联属性
	// 		关联类型 := 关联属性["关联类型"]
	// 		//形如👉 A商品  shangpin.S商品model  `json:"商品" gorm:"-"`
	// 		// sps := A拆分字符(字段.A类型_go)
	// 		if 关联类型 == "一对一属于" {
	// 			// err = global.GVA_DB.Preload("Good").Preload("SKU").Find(&list, "user_id = ?", userID).Error
	// 			db = db.Preload(字段.Name_go)
	// 		}
	// 	}
	// }
	关联查询(db, a.A组件)

	// db = db.Preload("A商品")
	// 按条件筛选查找👇
	// if info.A修改开始点 != nil && info.A修改结束点 != nil {
	// 	db = db.Where("updated_at BETWEEN ? AND ?", info.A修改开始点, info.A修改结束点)
	// } else if info.A修改开始点 != nil && info.A修改结束点 == nil {
	// 	db = db.Where("updated_at >=?", info.A修改开始点)
	// } else if info.A修改开始点 == nil && info.A修改结束点 != nil {
	// 	db = db.Where("updated_at <=?", info.A修改结束点)
	// }

	if info.A仅自己 {
		db = db.Where("用户id = ?", info.A用户id)
	}

	if len(info.IDS) > 0 {
		db = db.Where("id in ?", info.IDS)
	}

	if len(info.A筛选) > 0 {
		for _, 筛选 := range info.A筛选 {
			符号 := "="
			split := strings.Split(筛选, 符号)
			if len(split) > 1 {
				字段名 := split[0]
				字段值 := split[1]
				sql := fmt.Sprintf("%s %s '%s'", 字段名, 符号, 字段值)
				db = db.Where(sql)
			}
		}
	}

	err = db.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 排序👇
	var OrderStr string
	OrderStr = info.Sort
	OrderStr = A转小写(OrderStr)
	// OrderStr = "updated_at"
	if info.Order == "descending" {
		OrderStr = OrderStr + " desc"
	}
	db = db.Order(OrderStr)

	if limit != 0 {
		db = db.Limit(limit).Offset(offset)
	}

	// db = db.Debug()
	err = db.Find(models).Error
	if err != nil {
		return nil, 0, err
	}
	return
}

func (a *Sservice) A查设置() (models any, total int64, err error) {
	model, models, _ := A解构组件(a.A组件)
	db := global.GVA_DB.Model(model)

	err = db.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	err = db.Find(models).Error
	if err != nil {
		return nil, 0, err
	}
	return
}

func 关联查询(db *gorm.DB, 组件 *S组件) {
	// 关联查询形如👇
	// if a.A组件.Name == "订单" {
	// 	db = db.Preload("A明细.A商品").Preload("A明细.Asku")
	// }

	// 处理关联记录
	for _, 字段 := range 组件.A字段组 {
		if 字段.A类型 == "关联记录" {
			// 需要区分关联类型否？
			// 关联属性 := 字段.A关联属性
			// 关联类型 := 关联属性["关联类型"]
			// //形如👉 A商品  shangpin.S商品model  `json:"商品" gorm:"-"`
			// if 关联类型 == "一对一属于" {
			// 	// err = global.GVA_DB.Preload("Good").Preload("SKU").Find(&list, "user_id = ?", userID).Error
			// 	db = db.Preload(字段.Name_go)
			// }

			关联字段名 := 字段.Name_go
			order := "ASC"
			db = db.Preload(关联字段名, func(subDB *gorm.DB) *gorm.DB {
				return subDB.Order("updated_at " + order)
			})
			关联组件 := 字段.A关联组件
			上层关联字段名 := 关联字段名
			// 暂时只处理 2 层
			if 关联组件 != nil {
				for _, 字段 := range 关联组件.A字段组 {
					if 字段.A类型 == "关联记录" {
						关联字段名 := 字段.Name_go
						db = db.Preload(上层关联字段名 + "." + 关联字段名)
					}
				}
			}
		}
	}
}
